package wickethub.data;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.Normalizer;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.rating.RatingPanel;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;

import wickethub.domain.BlogPost;
import wickethub.domain.Resource;
import wickethub.domain.Snippet;
import wickethub.repository.ResourceRepository;
import wickethub.web.app.WicketHubWebSession;

public class Util {
	
	// TODO optimize
	public static String getTextForUrl(String text) {
		return Normalizer.normalize(text, Normalizer.Form.NFD)
			.trim().toLowerCase()
			.replaceAll("[\u0300-\u036F]", "")
			.replaceAll(" ", "-")
			.replaceAll("[^a-zA-Z0-9-]", "");
	}
	
	public static String abbreviate(String s) {
		return StringUtils.abbreviate(s, 37);
	}
	
	public static Set<String> getSetFromString(String s) {
		Set<String> set = new LinkedHashSet<String>();
		if (s != null) {
			String[] elements = StringUtils.split(s.toLowerCase(), ',');
    		for (String element : elements) {
    			set.add(element.trim());
    		}
		}
		return set;
	}
	
	public static String getStringFromSet(Set<String> set) {
		return StringUtils.join(set.iterator(), ", ");
	}
	
	public static String getJsonFromSet(Set<String> set) {
		return "['"+ StringUtils.join(set.iterator(), "', '")  +"']" + ";"; 
	}
	
	public static String getLuceneDirectory() {
		return "/opt/wickethub/lucene";
	}

	// FIXME this method smells bad...
	public static String getStringForResourceType(Resource r) {
		if (Snippet.class.isAssignableFrom(r.getClass())) {
			return "Code snippet";
		} else if (BlogPost.class.isAssignableFrom(r.getClass())) {
			return "Blog post";
		} else { // for other resource, default Component
			return "Component";
		} 
	}
	
	public static boolean isURLValid(String url) {
		try {

			URL u = new URL(url);
			HttpURLConnection connection = (HttpURLConnection)u.openConnection();
			
			if (connection.getResponseCode() > 400) { // 200 HTTP OK
				return false;
			}
			return true;
			
		} catch (Exception e) {
			return false;
		}
		
	}
	
	// this function somehow works but its impl smells -> FIXME
	public static String getTitleFromWebPage(String url) {
		try {
			URL u = new URL(url);
			
			HttpURLConnection connection = (HttpURLConnection)u.openConnection();
			connection.setFollowRedirects(true);
			connection.setRequestProperty(
					"User-Agent",
					"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8");

			if (connection.getResponseCode() > 400) { // 200 HTTP OK
				return null;
			}
			
			String s = new String();
			StringBuilder sb = new StringBuilder();
			String regex = ".*<title>(.*)</title>.*";
			
			BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
					
			while (!s.toLowerCase().matches(".*<title>.*")) {
				s = in.readLine();
				sb.append(s);
			}
			
			if (!s.isEmpty()) {
				sb.append(in.readLine());
				sb.append(in.readLine());
				Pattern pattern = Pattern.compile(regex, Pattern.DOTALL | Pattern.UNIX_LINES | Pattern.CASE_INSENSITIVE);
			    Matcher matcher = pattern.matcher(sb.toString());
			    if (matcher.find()) {
			    	String title = matcher.group(1).trim();
			    	return title;
			    }
			    
			}
			
			return null;
			
		} catch (Exception e) {
			return null;
		}
	}
	
	public static RatingPanel getRatingPanel(String id, final IModel<Resource> model, final ResourceRepository repo) {
		Resource resource = model.getObject();
		return new RatingPanel(id, new PropertyModel<Integer>(resource, "rating"), 
				new Model<Integer>(5),
				new PropertyModel<Integer>(resource, "timesRated"), 
				new AbstractReadOnlyModel<Boolean>() {
    				@Override
    				public Boolean getObject() {
    					return WicketHubWebSession.get().isRated(model.getObject());
    				}
    			},
				false) {
			
	        protected boolean onIsStarActive(int star) {
	        	return star + 1 <= Math.rint(model.getObject().getRating());
	        }
	
	        protected void onRated(int rating, AjaxRequestTarget target) {
	        	WicketHubWebSession.get().addRatedModule(model.getObject());
	        	model.getObject().addRating(rating);
	        	repo.save(model.getObject());
	        	
	        }
	        
    		@SuppressWarnings("unchecked")
			protected org.apache.wicket.Component newRatingLabel(String id, IModel rating, IModel nrOfVotes) {
    			Label label = new Label(id, "");
    			label.setVisible(false);
    			return label;
    		}
	        
	    };
	}

}